import { defineStore } from 'pinia'
import { computed } from 'vue'
import { BrowserGroups } from '@/constants/device-maintenance'
import { ReadDataTaskExecutedResult } from '@/types/signalr/read-data-task-executed-result'
import * as signalR from '@microsoft/signalr'
import { ElMessage } from 'element-plus'

class SignalRRetryPolicy implements signalR.IRetryPolicy {
  nextRetryDelayInMilliseconds(retryContext: signalR.RetryContext): number | null {
    return 10000 // 10 s
  }
}

export type ReadValueCallback = (result: ReadDataTaskExecutedResult) => void

export const useDeviceMaintenanceSignalRClientStore = defineStore(
  'device-maintenance-signalr-client',
  () => {
    const url = import.meta.env.VITE_DEVICE_MAINTENANCE_BASE_URL + '/browser-hub'
    const connection = new signalR.HubConnectionBuilder()
      .withUrl(url)
      .withAutomaticReconnect(new SignalRRetryPolicy())
      .build()
    const maps = new Map<string, ReadValueCallback>()
    const isConnected = computed(() => {
      return connection.state == signalR.HubConnectionState.Connected
    })

    async function connectServerAsync() {
      await connection.start()
      connection?.on('OnReadValueAsync', (result: ReadDataTaskExecutedResult) => {
        maps.forEach((callback, key) => {
          if (key == result.partId) {
            callback(result)
          }
        })
      })
      await connection?.invoke('AddToGroup', BrowserGroups.DeviceMaintenance)
    }

    async function subscribeAsync(partId: string, callback: ReadValueCallback) {
      maps.set(partId, callback)
    }

    async function unsubscribeAsync(partId: string) {
      if (maps.has(partId)) {
        maps.delete(partId)
      }
    }

    return {
      isConnected,
      connectServerAsync,
      subscribeAsync,
      unsubscribeAsync
    }
  }
)
